package ServerPackage;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;

import ClientPackage.ClientInfo;

/**
 * 	This class services a client. It is passed a Datagram packet for client from the server which
 *	is used for processing the request. The run method for this class will run till this thread 
 *  finishing the assignment.
 *  
 * 	@author Zhisheng Huang
 *	@version 1.0  1/23/2010
 */
public class ServerThread implements Runnable {
	/**
	 * Socket handle used for communication with the client
	 */
	private DatagramSocket _client;
	
	/**
	 * data packet that received from clients
	 */
	private DatagramPacket _receiveMessage;
	
	/**
	 * Current client Ip address 
	 */
	private InetAddress _clientIP; 
	
	/**
	 * Current client port number
	 */
	private int _clientListeningPort;
		
	/**
	 * These are the record for all trusted users
	 */
	public static ArrayList<ClientInfo> _onlineUserList = new ArrayList<ClientInfo>();
	
	
	
	
		
	public long finish = 0;
	public long start = 0;
		
	/**
	 * The constructor initializes the client socket handle with the one passed from the server
	 * @param receiveMessage - the targeted data to be processed
	 */
	public ServerThread(DatagramPacket receiveMessage) {	
		try {
			_client = new DatagramSocket();	
			_receiveMessage = receiveMessage;
			_client.setReceiveBufferSize(1024);
			_client.setSendBufferSize(1024);
		} catch (SocketException e) {
			System.out.println("there is some error setting up the buffer size.");
			e.printStackTrace();
		} //End catch
		
	} //End serviceThread
	
	/**
	 * This is the method that services individual clients. This will echo the sent 
	 * data back to the client. This method terminates when the client closes the 
	 * connection with the server
	 */
	public void run() {
		try{
			//Local variables
			byte[] sendData = new byte[1024];
			String text = new String(_receiveMessage.getData());
			int index=0;
			for(; index<text.length();index++){
				if(text.charAt(index)== '\0')
					break;	
			} //End for
			text = text.substring(0, index);			
			
			
			
			if(text.equalsIgnoreCase("login")){
				
				verify();
				
			} else if (checkList() && text.equalsIgnoreCase("list")){
				
				sendList();
				
			} else if ( checkList() && text.equalsIgnoreCase("logout")){
				logout();
			}
							
			
		} catch(Exception e){
			//There was some problem, log the exception
			e.printStackTrace();
		}//End catch
		
	}//End run method
	
	
	/**
	 * verify this client, if succeed, save the IP and Port into List
	 */
	public void verify(){
		
		//After you verify the client, you save all the information
		//And the public key, session key
		
		_onlineUserList.add(new ClientInfo(_receiveMessage.getAddress(),
				_receiveMessage.getPort(), "Alice"));
	}
	
	
	/**
	 * check whether this coming Client is trusted or not
	 */
	public boolean checkList(){
		
		
		//you could use a structure like this to implement check 
		//whether the client is trusted or not
		for(int i =0; i<_onlineUserList.size(); i++){
			if(_onlineUserList.get(i)._ip.equals(_receiveMessage.getAddress())
					&& _onlineUserList.get(i)._port == (_receiveMessage.getPort())){
				//if found, return true
				return true;
			}
		}
		
		return false;
	}
	
	
	/**
	 * send the List of on-line users to the client
	 */
	public void sendList(){
		
		try {
			byte [] byteToSend = getBytes(_onlineUserList);
			
			DatagramPacket sendPacket 
			= new DatagramPacket(byteToSend, byteToSend.length, 
					_receiveMessage.getAddress(), _receiveMessage.getPort());  
			
			_client.send(sendPacket);
			Thread.yield();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	/**
	 * logout and delete the record in the on-line list
	 */
	public void logout(){
		int i;
		for(i =0; i<_onlineUserList.size(); i++){
			if(_onlineUserList.get(i)._ip.equals(_receiveMessage.getAddress())
					&& _onlineUserList.get(i)._port == (_receiveMessage.getPort())){
				break;
			}
		}
		
		_onlineUserList.remove(i);
		
	}
	
	/**
	 * method used to generate byte array from object
	 * @param obj
	 * @return
	 * @throws java.io.IOException
	 */
	 public static byte[] getBytes(Object obj) throws java.io.IOException{
	      ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
	      ObjectOutputStream oos = new ObjectOutputStream(bos); 
	      oos.writeObject(obj);
	      oos.flush(); 
	      oos.close(); 
	      bos.close();
	      byte [] data = bos.toByteArray();
	      return data;
	  }

}//End class ServiceClass



